package com.rf.richfitwheel.common.utils;

import com.github.pagehelper.PageInfo;
import com.rf.richfitwheel.common.contants.Constant;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**convertTree
 * @ClassName : BusinessUtils
 * @Description :
 * @Author : GaoHuiMin
 * @Date : 2021/9/11 15:27
 * @Modifier :
 * @ModifyTime :
 */
public class BusinessUtils {

    private static BusinessUtils businessUtils;

    @PostConstruct
    public void init() {
        businessUtils = this;
    }

    private BusinessUtils() {
        super();
    }

    /*
     * @Title       : getTable
     * @Description : 页面表头、表格（单层表头，属性自定义）
     * @Author      : GaoHuiMin
     * @Pate        : 2021/9/11 15:29
     * @Param       : [list, names, propList]
     * @return      :
     **/
    public static Map<String, Object> getTable(List<?> list, List<String> names, List<String> propList) {
        List<TableHeadBo> headList = new ArrayList<>();
        for (int i = 0; i < names.size(); i++) {
            String name = names.get(i);
            TableHeadBo bo = new TableHeadBo();
            bo.setLabel(name);
            bo.setProp(propList.get(i));
            headList.add(bo);
        }
        Map<String, Object> map = new HashMap<>();
        map.put(Constant.TABLE_HEADE, headList);
        map.put(Constant.TABLE_BODY, list);
        return map;
    }

    /**
     * @Title       : getPageTable
     * @Description : 页面表头、表格，（包含分页信息）
     * @Author      : GaoHuiMin
     * @Pate        : 2021/9/13 10:59
     * @Param       : [list, names, propList, pageInfo]
     * @return      :
     **/
    public static PageUtil getPageTable(List<?> list, List<String> names, List<String> propList, PageInfo<?> pageInfo) {
        List<TableHeadBo> headList = new ArrayList<>();
        names.forEach(name -> {
            int index = names.indexOf(name);
            TableHeadBo bo = new TableHeadBo();
            bo.setLabel(name);
            bo.setProp(propList.get(index));
            headList.add(bo);
        });
        return new PageUtil(pageInfo, headList, list);
    }

    //转换树形结构
    public static <T> List<T> convertTree(List<T> list) {
        List<T> parentList = new ArrayList<>();
        try {
            for (T t : list) {
                Class<? extends Object> tClass = t.getClass();
                List<String> fieldList = getField(t);
                String id = "";
                String parentid = "";
                if("id".equals(fieldList.get(0))) {
                    //获取get方法
                    Method method = tClass.getMethod("get"+strFirstUpper(fieldList.get(0)));
                    //取值
                    id = (String) method.invoke(t);
                }
                if("parentid".equals(fieldList.get(1))) {
                    Method method = tClass.getMethod("get"+strFirstUpper(fieldList.get(1)));
                    parentid = (String) method.invoke(t);
                }
                if("parentId".equals(fieldList.get(1))) {
                    Method method = tClass.getMethod("get"+strFirstUpper(fieldList.get(1)));
                    parentid = (String) method.invoke(t);
                }

                ArrayList<T> childrenList = new ArrayList<>();
                if("0".equals(parentid) || StringUtils.isBlank(parentid)) {
                    parentList.add(t);
                }
                //遍历list
                for (T t2 : list) {
                    Class<? extends Object> tClass2 = t2.getClass();
                    List<String> fieldList2 = getField(t2);
                    String pid2 = "";
                    if("parentid".equals(fieldList2.get(1))) {
                        Method method2 = tClass2.getMethod("get"+strFirstUpper(fieldList2.get(1)));
                        pid2 = (String) method2.invoke(t2);
                    }
                    if("parentId".equals(fieldList2.get(1))) {
                        Method method2 = tClass2.getMethod("get"+strFirstUpper(fieldList2.get(1)));
                        pid2 = (String) method2.invoke(t2);
                    }
                    if(id.equals(pid2)) {
                        childrenList.add(t2);
                    }
                }
                if("children".equals(fieldList.get(2))) {
                    //得到所有属性
                    Field[] fieldArrays = tClass.getDeclaredFields();
                    Field field = null;
                    for (int i = 0; i < fieldArrays.length; i++) {
                        Field field2 = fieldArrays[i];
                        String name = field2.getName().replace("$cglib_prop_", "");
                        if("children".equals(name)) {
                            field = field2;
                        }
                    }
                    //set方法
                    Method setMethod = tClass.getDeclaredMethod("set"+strFirstUpper(fieldList.get(2)), field.getType());
                    // 结算代码问题整改
                    ReflectionUtils.makeAccessible(setMethod);
                    //赋值
                    setMethod.invoke(t, childrenList);
                }
                //childList
                if("childList".equals(fieldList.get(2))) {
                    //得到所有属性
                    Field[] fieldArrays = tClass.getDeclaredFields();
                    Field field = null;
                    for (int i = 0; i < fieldArrays.length; i++) {
                        Field field2 = fieldArrays[i];
                        String name = field2.getName().replace("$cglib_prop_", "");
                        if("childList".equals(name)) {
                            field = field2;
                        }
                    }
                    //set方法
                    Method setMethod = tClass.getDeclaredMethod("set"+strFirstUpper(fieldList.get(2)), field.getType());
                    // 结算代码问题整改
                    ReflectionUtils.makeAccessible(setMethod);
                    //赋值
                    setMethod.invoke(t, childrenList);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
        return parentList;
    }

    private static <T> List<String> getField(T t) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        List<String> list = new ArrayList<>(3);
        list.add("1");
        list.add("2");
        list.add("3");
        Class<? extends Object> tClass = t.getClass();
        //得到所有属性
        Field[] fieldArrays = tClass.getDeclaredFields();
        for (Field field : fieldArrays) {
            // 结算代码问题整改
            ReflectionUtils.makeAccessible(field);
            String name = field.getName().replace("$cglib_prop_", "");
            if("id".equals(name)) {
                list.set(0, name);
            }
            if("parentid".equals(name)) {
                list.set(1, name);
            }
            if("parentId".equals(name)) {
                list.set(1, name);
            }
            if("children".equals(name)) {
                list.set(2, name);
            }
            if("childList".equals(name)) {
                list.set(2, name);
            }
        }
        return list;
    }

    //预算编制定制，因为子父间关系是 通过projectId 和 parentId来体现的
    private static <T> List<String> getFieldBudgetMarking(T t) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        List<String> list = new ArrayList<>(3);
        list.add("1");
        list.add("2");
        list.add("3");
        Class<? extends Object> tClass = t.getClass();
        //得到所有属性
        Field[] fieldArrays = tClass.getDeclaredFields();
        for (Field field : fieldArrays) {
            // 结算代码问题整改
            ReflectionUtils.makeAccessible(field);
            String name = field.getName().replace("$cglib_prop_", "");
            if("projectId".equals(name)) {
                list.set(0, name);
            }
            if("parentid".equals(name)) {
                list.set(1, name);
            }
            if("parentId".equals(name)) {
                list.set(1, name);
            }
            if("children".equals(name)) {
                list.set(2, name);
            }
            if("childList".equals(name)) {
                list.set(2, name);
            }
        }
        return list;
    }


    //转换树形结构,预算编制定制
    public static <T> List<T> convertTreeBudgetMarking(List<T> list) {
        List<T> parentList = new ArrayList<>();
        try {
            for (T t : list) {
                Class<? extends Object> tClass = t.getClass();
                List<String> fieldList = getFieldBudgetMarking(t);
                String id = "";
                String parentid = "";
                if("projectId".equals(fieldList.get(0))) {
                    //获取get方法
                    Method method = tClass.getMethod("get"+strFirstUpper(fieldList.get(0)));
                    //取值
                    id = (String) method.invoke(t);
                }
                if("parentid".equals(fieldList.get(1))) {
                    Method method = tClass.getMethod("get"+strFirstUpper(fieldList.get(1)));
                    parentid = (String) method.invoke(t);
                }
                if("parentId".equals(fieldList.get(1))) {
                    Method method = tClass.getMethod("get"+strFirstUpper(fieldList.get(1)));
                    parentid = (String) method.invoke(t);
                }

                ArrayList<T> childrenList = new ArrayList<>();
                if("0".equals(parentid) || StringUtils.isBlank(parentid)) {
                    parentList.add(t);
                }
                //遍历list
                for (T t2 : list) {
                    Class<? extends Object> tClass2 = t2.getClass();
                    List<String> fieldList2 = getFieldBudgetMarking(t2);
                    String pid2 = "";
                    if("parentid".equals(fieldList2.get(1))) {
                        Method method2 = tClass2.getMethod("get"+strFirstUpper(fieldList2.get(1)));
                        pid2 = (String) method2.invoke(t2);
                    }
                    if("parentId".equals(fieldList2.get(1))) {
                        Method method2 = tClass2.getMethod("get"+strFirstUpper(fieldList2.get(1)));
                        pid2 = (String) method2.invoke(t2);
                    }
                    if(id.equals(pid2)) {
                        childrenList.add(t2);
                    }
                }
                if("children".equals(fieldList.get(2))) {
                    //得到所有属性
                    Field[] fieldArrays = tClass.getDeclaredFields();
                    Field field = null;
                    for (int i = 0; i < fieldArrays.length; i++) {
                        Field field2 = fieldArrays[i];
                        String name = field2.getName().replace("$cglib_prop_", "");
                        if("children".equals(name)) {
                            field = field2;
                        }
                    }
                    //set方法
                    Method setMethod = tClass.getDeclaredMethod("set"+strFirstUpper(fieldList.get(2)), field.getType());
                    // 结算代码问题整改
                    ReflectionUtils.makeAccessible(setMethod);
                    //赋值
                    setMethod.invoke(t, childrenList);
                }
                //childList
                if("childList".equals(fieldList.get(2))) {
                    //得到所有属性
                    Field[] fieldArrays = tClass.getDeclaredFields();
                    Field field = null;
                    for (int i = 0; i < fieldArrays.length; i++) {
                        Field field2 = fieldArrays[i];
                        String name = field2.getName().replace("$cglib_prop_", "");
                        if("childList".equals(name)) {
                            field = field2;
                        }
                    }
                    //set方法
                    Method setMethod = tClass.getDeclaredMethod("set"+strFirstUpper(fieldList.get(2)), field.getType());
                    // 结算代码问题整改
                    ReflectionUtils.makeAccessible(setMethod);
                    //赋值
                    setMethod.invoke(t, childrenList);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
        return parentList;
    }

    private static String strFirstUpper(String str) {
        return str.replaceFirst(str.substring(0, 1), str.substring(0, 1).toUpperCase());
    }

    /**
     * 2位编码
     *@param
     */
    public static String getCode(String serviceCode) throws Exception {
        String lastSub = serviceCode.substring(serviceCode.length()-2, serviceCode.length());
        if(Integer.valueOf(lastSub) == 99){
            throw new Exception("TreeTooLongException");
        }
        String firstSub = serviceCode.substring(0, serviceCode.length()-2);
        if(Integer.valueOf(lastSub.substring(0,1)) == 0){
            Integer tmpCode = Integer.valueOf(lastSub.substring(1,2))+1;
            if(tmpCode == 10){
                String service = tmpCode.toString();
                return firstSub+service;
            }else{
                String service = "0"+tmpCode;
                return firstSub+service;
            }
        }else{
            Integer tmpCode = Integer.valueOf(lastSub)+1;
            String service = tmpCode.toString();
            return firstSub+service;
        }
    }

    /**
     * 3位编码
     *
     * @param
     */
    public static String get3Code(String serviceCode) throws Exception {
        String lastSub = serviceCode.substring(serviceCode.length() - 3,
                serviceCode.length()); // 截取后3位
        if (Integer.valueOf(lastSub) == 999) {
            throw new Exception("TreeTooLongException");
        }
        String firstSub = serviceCode.substring(0, serviceCode.length() - 3);// 除最后3位字符串
        Integer temCode = Integer.parseInt(lastSub)+1;
        String tempStr = String.valueOf(temCode);
        for(int i = tempStr.length();i<3;i++){
            tempStr="0"+tempStr;
        }
        return firstSub+tempStr;
    }

    /**
     * @Description : 判断机构机构级别
     */
    public static String assertGroupLevel(String groupCode){
        String level = "";
        if(StringUtils.isNotBlank(groupCode)){
            //以10202210 开头的编码都被认为是总部单位
            if(groupCode.startsWith(Constant.GROUP_CODE_HEAD_PREFIX)||"10".equals(groupCode)){
                level = Constant.GROUP_LEVEL_HEAD;
            }
            //除了10202210 以外的8位都是地区公司
            else if(groupCode.length() == 8){
                level = Constant.GROUP_LEVEL_PLACE;
            }
            //非总部的地区公司下面的12位、16位等多于8位的节点都是该地区的基层单位
            else if(groupCode.length() > 8){
                level = Constant.GROUP_LEVEL_BASIC;
            }
        }
        return level;
    }

    public static void setPropertyValue(Object obj) throws Exception {
        Class<? extends Object> cls = obj.getClass();
        /** 首先先获得cls里边的所有属性 **/
        Field[] clsField = cls.getDeclaredFields();

        for (int i = 0; i < clsField.length; i++) {
            String methodName = (clsField[i].getName().charAt(0) + "")
                    .toUpperCase()
                    + clsField[i].getName().substring(1);
            if(!"SerialVersionUID".equals(methodName)){
                clsMap.put(clsField[i].toString(), clsField[i].getType());
                Method get = cls.getDeclaredMethod("get" + methodName);
                Object value = get.invoke(obj);
                defaultPropertyValue(clsField[i], clsField[i].getType().getName(),
                        value, obj, cls);
            }
        }
    }


    /** 属性与属性类型的map **/
    static Map<String, Object> clsMap = new HashMap<String, Object>();

    private static void defaultPropertyValue(Field field, String type,
                                             Object value, Object obj, Class<? extends Object> cls)
            throws Exception {
        if("BigDecimal".equals(type) || "java.math.BigDecimal".equals(type)) {
            try {
                String methodName = (field.getName().charAt(0) + "")
                        .toUpperCase()
                        + field.getName().substring(1);
                Class<?> c = (Class<?>) clsMap.get(field.toString());
                if (value == null) {
                    Method set = obj.getClass().getDeclaredMethod(
                            "set" + methodName, new Class[] { c });
                    set.invoke(obj, BigDecimal.ZERO);
                }
            } catch (Exception e) {
            }
        }else if (type.equals("int") || "java.lang.Integer".equals(type)) {
            try {
                String methodName = (field.getName().charAt(0) + "")
                        .toUpperCase()
                        + field.getName().substring(1);
                Class<?> c = (Class<?>) clsMap.get(field.toString());
                if (value == null) {
                    Method set = obj.getClass().getDeclaredMethod(
                            "set" + methodName, new Class[] { c });
                    set.invoke(obj, new Object[] { 0 });
                }
            } catch (Exception e) {
            }
        } else if (type.equals("double") || "java.lang.Double".equals(type)) {
            try {
                String methodName = (field.getName().charAt(0) + "")
                        .toUpperCase()
                        + field.getName().substring(1);
                Class<?> c = (Class<?>) clsMap.get(field.toString());
                if (value == null) {
                    Method set = obj.getClass().getDeclaredMethod(
                            "set" + methodName, new Class[] { c });
                    set.invoke(obj, 0.0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (type.equals("Date") || "java.util.Date".equals(type)) {

            try {
                String methodName = (field.getName().charAt(0) + "")
                        .toUpperCase()
                        + field.getName().substring(1);
                Class<?> c = (Class<?>) clsMap.get(field.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try {
                String methodName = (field.getName().charAt(0) + "")
                        .toUpperCase()
                        + field.getName().substring(1);
                Class<?> c = (Class<?>) clsMap.get(field.toString());
                if (value == null) {
                    Method set = obj.getClass().getDeclaredMethod(
                            "set" + methodName, new Class[] { c });
                    set.invoke(obj, "");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}
